package ch.exm.storm.query.selection;

import static ch.exm.storm.conditions.arguments.ArgumentsFactory.getActualArgument;

import ch.exm.storm.conditions.arguments.Argument;

public class Selection {
	
	public enum Aggregation {
		NONE(""), AVG("avg"), SUM("sum"), MIN("min"), MAX("max"), COUNT("count");
		
		private String name;
		
		Aggregation(String name) {
			this.name = name;
		}
		
		@Override
		public String toString() {
			return name;
		}
		
		public String decorateStatement(String statement) {
			if (this == NONE) return statement;
			return statement == null ? null : name + "(" + statement + ")"; 
		}
	}

	private Object selected;
	private Aggregation aggregation;
	private boolean distinct = false;
	
	public Selection(Object selected) {
		this(selected, Aggregation.NONE, false);
	}

	public Selection(Object selected, boolean distinct) {
		this(selected, Aggregation.NONE, distinct);
	}
	
	public Selection(Object selected, Aggregation aggregation) {
		this(selected, aggregation, false);
	}
	
	public Selection(Object selected, Aggregation aggregation, boolean distinct) {
		this.selected = selected;
		this.aggregation = aggregation == null ? Aggregation.NONE : aggregation;
		this.distinct = distinct;
	}

	public Object getSelected() {
		return selected;
	}
	
	public Argument getSelectedArgument() {
		return getActualArgument(getSelected());
	}
	
	public Class<?> getSelectedClass() {
		return getSelectedArgument().getRootArgumentClass();
	}

	public Aggregation getAggregation() {
		return aggregation;
	}
	
	public boolean isDistinct() {
		return distinct;
	}
	
	public String getSelectionStatement(String argument) {
		return aggregation.decorateStatement((distinct ? "distinct " : "") + argument);
	}

	@Override
	public String toString() {
		return getSelectionStatement(selected.toString());
	}
}
